/*
 * Copyright (c) 2021-2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define LOG_TAG "main"

#include <iostream>
#include <memory>
#include <thread>
#include <chrono>
#include "foundation/osal/utils/util.h"

#ifdef OHOS_LITE
#include "histreamer/hiplayer.h"
#else
#include "i_engine_factory.h"

extern "C" {
__attribute__((visibility("default"))) OHOS::Media::IEngineFactory* CreateEngineFactory();
}
#endif

using namespace OHOS::Media;
enum class MusicClass { MP3, AAC_LC, AAC_HE, AAC_HE2, AAC_LOAS, M4A, WAV, APE, FLAC, OGG, AVS3DA, AVS3GP, TS };

constexpr bool SINGLE_LOOP = true;

std::string GetMusicUri(MusicClass musicClass)
{
    std::string uri = RESOURCE_DIR "/";
    //std::string uri = "http://192.168.0.152/resource/short_music.mp3";
    //std::string uri = "http://img.51miz.com/preview/sound/00/26/73/51miz-S267356-423D33372.mp3";
    //std::string uri = "https://img.51miz.com/preview/sound/00/26/73/51miz-S267356-423D33372.mp3";
    //std::string uri = "http://ls-open.qingting.fm/live/389/64k.m3u8?deviceid=00000000-0000-0000-0000-000000000000&format=aac";
    if (uri != RESOURCE_DIR "/") {
        return uri;
    }
    switch (musicClass) {
        case MusicClass::MP3:
            uri += "MP3/MP3_LONG_48000_32.mp3";
            break;
        case MusicClass::AAC_LC:
            uri += "AAC/AAC_LONG_48000_32.aac";
            break;
        case MusicClass::AAC_HE:
            uri += "AAC/AAC_LONG_48000_32.aac";
            break;
        case MusicClass::AAC_HE2:
            uri += "AAC/AAC_LONG_48000_32.aac";
            break;
        case MusicClass::AAC_LOAS:
            uri += "AAC/AAC_LONG_48000_32.aac";
            break;
        case MusicClass::M4A:
            uri += "M4A/MPEG-4_48000_32_LONG.m4a";
            break;
        case MusicClass::APE:
            uri += "APE/APE_16000-16_1.ape";
            break;
        case MusicClass::FLAC:
            uri += "FLAC/FALC_11025_16_2.flac";
            break;
        case MusicClass::OGG:
            uri += "OGG/64k_48000_2.ogg";
            break;
        case MusicClass::WAV:
            uri += "WAV/vorbis_48000_32_SHORT.wav";
            break;
        case MusicClass::AVS3DA:
            uri += "AVS3DA/21_Bluebirds_ADM_bed5.1.2_obj2_ADM.mp4";
            // uri += "AVS3DA/21_ANYTHING_YOU_WANT_ADM_bed5.1.2_obj2_ADM.mp4";
            break;
        case MusicClass::AVS3GP:
            uri += "../demo_resource/video/1h264_320x240_60.3gp";
            break;
        case MusicClass::TS:
            uri += "TS/h264_aac_270p_10r_voiced.ts"; // h264_320x240_60.ts
            break;
        default:
            uri += "MP3/MP3_LONG_48000_32.mp3";
            break;
    }
    return uri;
}

#ifdef VIDEO_SUPPORT
enum class VideoClass { H264, AVS3GP, TS };

std::string GetVideoUri(VideoClass videoClass)
{
    std::string uri = RESOURCE_DIR "/";
    switch (videoClass) {
        case VideoClass::H264:
            uri += "MP4/AVC_1024x526_25FPS.mp4"; //"test.mp4"; //"11_AVC_640x480_25.000fps.mp4";
            break;
        case VideoClass::AVS3GP:
            uri += "../demo_resource/video/1h264_320x240_60.3gp";
            break;
        case VideoClass::TS:
            uri += "TS/h264_320x240_60.ts"; // h264_aac_270p_10r_voiced
            break;
        default:
            break;
    }
    return uri;
}
#endif

#ifdef OHOS_LITE
void ReceiveUserCmd(PlayerInterface* player, int playSeconds)
#else
void ReceiveUserCmd(IPlayerEngine* player, int playSeconds)
#endif
{
    std::string cmd;
    auto beginTime = std::chrono::high_resolution_clock::now();
    do {
        if (playSeconds > 0) {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            auto endTime = std::chrono::high_resolution_clock::now();
            auto elapsedTime = std::chrono::duration_cast<std::chrono::seconds>(endTime - beginTime);
            if (elapsedTime.count() <= playSeconds) {
                continue;
            }
            break;
        }
        std::cin >> cmd;
        if (cmd == "seek") {
            int pos;
            std::cin >> pos;
#ifdef OHOS_LITE
            player->Rewind(pos, 0);
#else
            player->Seek(pos, PlayerSeekMode::SEEK_CLOSEST);
#endif
        } else if (cmd == "getPos") {
#ifdef OHOS_LITE
            int64_t now = 0;
            player->GetCurrentPosition(now);
#else
            int32_t now = 0;
            player->GetCurrentTime(now);
#endif
            std::cout<<"now "<< now/1000 <<std::endl;
        } else if (cmd == "getDua") {
#ifdef OHOS_LITE
            int64_t duration = 0;
#else
            int32_t duration = 0;
#endif
            player->GetDuration(duration);
            std::cout<<"duration "<< duration/1000 <<std::endl;
        } else if (cmd == "pause") {
            player->Pause();
        } else if (cmd == "play") {
            player->Play();
        }
    } while (cmd != "exit");
}

//#define TEST_LITE_PLAYER_TWO_TIMES
#ifndef TEST_LITE_PLAYER_TWO_TIMES

int main(int argc, char* argv[])
{
    std::string url;
    int playSeconds = 0;
    if (argc < 2) {
        std::cout << "Please use this cmd to play url:  histreamer_player url" << std::endl;
    } else {
        url = argv[1];
        if (argc >= 3) {
            playSeconds = atoi(argv[2]);
        }
    }
#ifdef OHOS_LITE
    std::cout << "Use media_lite interface player." << std::endl;
    auto player = OHOS::Media::CreateHiPlayer();
    player->Init();
#ifdef VIDEO_SUPPORT
    OHOS::Media::Source source(GetVideoUri(VideoClass::H264));
#else
    OHOS::Media::Source source(GetMusicUri(MusicClass::MP3));
#endif
    player->SetSource(source);
    player->SetLoop(SINGLE_LOOP);
#else
    std::cout << "Use media_standard interface player." << std::endl;
    auto engineFactory = std::unique_ptr<OHOS::Media::IEngineFactory>(CreateEngineFactory());
    auto player = engineFactory->CreatePlayerEngine();
    if (!url.empty()) {
        player->SetSource(url);
    } else {
#ifdef VIDEO_SUPPORT
        player->SetSource(GetVideoUri(VideoClass::H264));
#else
        player->SetSource(GetMusicUri(MusicClass::MP3));
#endif
    }
    player->SetLooping(SINGLE_LOOP);
#endif
    player->Prepare();
    player->Play();
    //std::cin.get();
//    std::this_thread::sleep_for(std::chrono::seconds(10));
//    std::cout << "Main Puase called." << std::endl;
//    player->Pause();
    //std::cin.get();
//    std::this_thread::sleep_for(std::chrono::seconds(3));
//    std::cout << "Main Play called." << std::endl;
//    player->Play();
    //std::cin.get();
    ReceiveUserCmd(player.get(), playSeconds);
    //std::this_thread::sleep_for(std::chrono::seconds(30));
    //std::cout << "Main Stop called." << std::endl;
    //player->Stop();
    //    std::cin.get();
    return 0;
}

#else

bool g_playFinished = false;

class PlayerCallbackImpl : public PlayerCallback {
    void OnPlaybackComplete() override {
        g_playFinished = true;
    }

    void OnError(int32_t errorType, int32_t errorCode) override {

    }

    void OnInfo(int type, int extra) override {

    }

    void OnVideoSizeChanged(int width, int height) override {

    }

    void OnRewindToComplete() override {

    }
};

void StartPlayer()
{
    std::cout << "Use media_lite interface player." << std::endl;
    g_playFinished = false;
    auto player = OHOS::Media::CreateHiPlayer();
    player->Init();
    auto callback = std::make_shared<PlayerCallbackImpl>();
    player->SetPlayerCallback(callback);
    OHOS::Media::Source source("../../resource/short_music.mp3");
    player->SetSource(source);
    player->SetLoop(false);
    player->Prepare();
    player->Play();
    while (!g_playFinished) {
        //OSAL::SleepFor(50);
    }
}

int main(int argc, char* argv[])
{
    StartPlayer();
    StartPlayer();
    return 0;
}
#endif